#include "stdafx.h"
#include "getopt.h"

namespace cpputils
{

bool command_line_arguments::option_arguments::empty() const
{
	return Args.empty();
}

int command_line_arguments::option_arguments::size() const
{
	return Args.size();
}

const string& command_line_arguments::option_arguments::operator[](int I) const
{
	if (I >= size())
		throw command_line_option_error("Require at least " + to_string(I + 1) + " " + get_option_name() + "(s)");
	return Args[I];
}

const string& command_line_arguments::option_arguments::get() const
{
	if (empty()) throw command_line_option_error("Require " + get_option_name());
	if (size() > 1) throw command_line_option_error("Duplicate " + get_option_name());
	return Args[0];
}

string command_line_arguments::option_arguments::get_or_default(const string& Default) const
{
	if (empty()) return Default;
	return get();
}

const vector<string>& command_line_arguments::option_arguments::get_all() const
{
	return Args;
}

void command_line_arguments::option_arguments::add(const string& S)
{
	Args.push_back(S);
}

string command_line_arguments::option_arguments::get_option_name() const
{
	if (Opt.names.empty()) return "command-line argument";
	return "option --" + Opt.names[0];
}

command_line_arguments::command_line_arguments()
{
}

command_line_arguments::command_line_arguments(const command_line_options& Opts, subarray<const command_line_argument> Args)
{
	build(Opts, Args);
}

void command_line_arguments::clear()
{
	reset_vector(OptArgs);
	CmdLineArgs.reset();
	OptMap.clear();
}

void command_line_arguments::build(const command_line_options& Opts, subarray<const command_line_argument> Args)
{
	clear();
	Empty = Args.empty();
	for (int I = 0; I < Opts.size(); I++)
		for (int J = 0; J < (int)Opts[I].names.size(); J++)
			OptMap[Opts[I].names[J]] = I;
	OptArgs.resize(Opts.size());
	CmdLineArgs.reset(new option_arguments);
	for (int I = 0; I < Args.size(); I++)
		(*this)[Args[I].option].add(Args[I].argument);
}

bool command_line_arguments::empty() const
{
	return Empty;
}

const command_line_arguments::option_arguments& command_line_arguments::operator[](const string& S) const
{
	if (S.empty()) return *CmdLineArgs;
	map<string, int>::const_iterator It = OptMap.find(S);
	if (It == OptMap.end()) throw command_line_option_error("Unknown option --" + S);
	return OptArgs[It->second];
}

command_line_arguments::option_arguments& command_line_arguments::operator[](const string& S)
{
	if (S.empty()) return *CmdLineArgs;
	map<string, int>::iterator It = OptMap.find(S);
	if (It == OptMap.end()) throw command_line_option_error("Unknown option --" + S);
	return OptArgs[It->second];
}

}
